home *** CD-ROM | disk | FTP | other *** search
- Path: news.larc.nasa.gov!amiga-request
- From: amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator)
- Subject: v91i028: CShell 5.00 - alternative command interface, Part02/06
- Reply-To: <umueller@iiic.ethz.ch>
- Newsgroups: comp.sources.amiga
- Message-ID: <comp.sources.amiga:v91i028@ab20.larc.nasa.gov>
- References: <comp.sources.amiga:v91i027@ab20.larc.nasa.gov>
- Date: 03 Mar 91 21:56:05 GMT
- Approved: tadguy@uunet.UU.NET (Tad Guy)
- X-Mail-Submissions-To: amiga@uunet.uu.net
- X-Post-Discussions-To: comp.sys.amiga.misc
-
- Submitted-by: <umueller@iiic.ethz.ch>
- Posting-number: Volume 91, Issue 028
- Archive-name: shells/cshell-5.00/part02
-
- #!/bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 2 (of 6)."
- # Contents: changes.doc rawcon.c sub.c
- # Wrapped by tadguy@ab20 on Sun Mar 3 16:55:58 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'changes.doc' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'changes.doc'\"
- else
- echo shar: Extracting \"'changes.doc'\" \(13639 characters\)
- sed "s/^X//" >'changes.doc' <<'END_OF_FILE'
- XOverview
- X
- XThe new CShell 4.9 is no longer adequate to low end systems, it's too large
- Xand consumes too much memory. I advise everybody who doesn't own a hard
- Xdrive to stick with the old versions. For those who can afford to run it,
- Xhowever, this version is a practical tool in command mode and a powerful
- Xlanguage for writing scripts while remaining compatible with its old
- Xscripts. As the version number 4.9 suggests, I'm note quite done yet, and
- Xthere might be bugs left. I count on you to report them to me. The source
- Xis not included this time, but still available.
- X
- XSome of the new features:
- X
- X- works fine on an Amiga 3000 and under Kickstart 2.0
- X- is residentable
- X- file name completion with TAB
- X- freely programmable command line editing keys
- X- many new editing functions
- X- jump scrolling (three lines scrolled in one step, useful in interlace)
- X- automatic cd (type 'system' instead of 'cd system')
- X- quick cd (cd knows about all directories on your HD and jumps directly)
- X- ~ stands for previous current directory
- X- special support for the closing kickstart 2.0 gadget
- X- you can 'rback' programs by adding a single '&' to the command line
- X- it is possible to install menus to the console window
- X- some internal functions csh have become faster
- X- runs on VT terminals again, even command line editing works now
- X- many builtin functions now like 'echo @strleft( hello 3 )'
- X- you can finally use foreign character sets
- X- any letter can be coded using backslash: echo \101 ouputs 'A'
- X- more startup options: -b (priority -1) -t (terminal) -k (no ^C) etc.
- X- automatic rx-ing: you can 'rx' .rexx files by typing their name
- X- ^D now aborts batchfiles like under AmigaDOS
- X- will 'source' files with script bit set
- X- limit of 256 arguments removed
- X- limit of 20 commands per line removed
- X- limit of 256 bytes per source line extended to 512
- X
- XNew commands (and options):
- X
- X- 'addbuffers' accepts any number drive/buffer pairs
- X- 'action' sends a action request to a file class
- X- 'alias'es can have more than one argument
- X- 'alias'es can prevent wild card expansion
- X- 'ascii' shows an ascii table
- X- 'assign' accepts any number logical/physical pairs
- X- 'assign' can create late/nonbinding assigns under kick 2.0
- X- 'cd' has an option to generate the list of all your directories
- X- 'class' defines a class of files and the actions allowed on them
- X- 'close' without arguments closes all open files
- X- 'cls' clears the screen, but now also works on a vt terminal
- X- 'copy' now copies the protection bits but clears archive bit
- X- 'copy -f' now 'freshens' like zoo. NOTE: *incompatible* with 4.02
- X- 'date' has a stopwatch built in
- X- 'dir' can sort forwards and backwards by name, size or time.
- X- 'dir' can hide .info files and files with the h-bit set
- X- 'dir' can show differences between directories
- X- 'dir' can show filenotes and file types
- X- 'echo' has an option to print to stderr
- X- 'exec' works better now
- X- 'filenote' can display filenotes, too
- X- 'getenv' reads a ARP or ENV: environment variable
- X- 'head', a filter, displays the first n lines of stdin
- X- 'input' can get characters in single character mode (!)
- X- 'info' also gives information on a single device
- X- 'linecnt', a filter, counts number of lines
- X- 'man' gets documentation to a shell command
- X- 'mem' can show only chip, only fast or bytes used sinc last mem -s
- X- 'menu' adds a menu
- X- 'mv' now clears the archive bit
- X- 'path' can also be used to set the path, not only to list it
- X- 'protect' can clear and set bits without disturbing the others
- X- 'ps' by default only shows the basenames of the started commands
- X- 'qsort' quicksorts from stdin to stdout
- X- 'readfile' completely reads a file and stores it in a variable
- X- 'rxsend' can receive results (now it's useful!)
- X- 'search' is much faster and has new output
- X- 'setenv' is used to set ENV: variables
- X- 'tail', a filter, prints the last lines of a file
- X- 'tee' copies stdin to stdout and stderr
- X- 'truncate' cuts the width of an ascii file
- X- 'touch' now clears the archive bit
- X- 'uniq' removes consecutive identical lines
- X- 'usage' shows the usage of a command
- X- 'waitforport' waits for an (arexx) port
- X- 'whereis' looks for a file on your hard drive
- X
- XNew system variables:
- X
- X- '_every' contains a command to be executed before the prompt appears
- X- '_hilite' holds the highlighting attributes
- X- '_history' now can be set to 0, which disables history
- X- '_kick2x' indicates whether V36 dos.library could be opened
- X- '_lcd' is the last current directoy
- X- '_minrows' is the minimum number of rows a window must have to quickscroll
- X- '_nobreak', if set, disables ^C
- X- '_noreq' disables system requesters
- X- '_path' no more need slashes at the end of directories
- X- '_prompt' now has many special symbols like %t for current time
- X- '_qcd' holds the name of the file where the directoy list for cd is stored
- X- '_rxpath' stores the list of directories where .rexx files reside
- X- '_scroll' contains the scroll jump or 0 for no quick scrolling
- X- '_terminal' indicates wheter or not shell was started in terminal mode
- X- '_titlebar' can have special %-symbols like _prompt
- X- '_tool_xxx' holds default tools for file ending .xxx
- X- '_version' is the current shell version number
- X
- XFunctions:
- X
- X- @abbrev is true if the str1 is an abbreviation of str2
- X- @abs returns absolute value of <num>
- X- @appext appends an extension to a string
- X- @availmem returns free 'chip', 'fast' or otherwise total memory
- X- @basename returns the file name without path
- X- @center centers a string
- X- @checkport indicates if given port exists
- X- @clinum returns the number of the given process
- X- @complete returns the first word an abbreviation matches
- X- @concat concats all args in one blank separated string
- X- @confirm gets confirmation for all its arguments
- X- @dectohex returns a string representing number in hex
- X- @delword returns a string with the n-th word deleted.
- X- @delwords deletes the next m words from the n-th.
- X- @dirs returns the directories among the given file names
- X- @drive outputs the drive ( device ) name associated to path
- X- @drives outputs all available drives
- X- @exists tells whether a file exists or not
- X- @fileblks returns the # of blocks needed for the files
- X- @filelen count the total number of bytes of the given files
- X- @fileprot returns a string like ---arwed
- X- @filereq brings up the arp file requester and returns the selected file
- X- @files gives you the files among those names, no directories
- X- @freebytes the number of free bytes on the given path
- X- @freeblks the number of free blocks on the given path
- X- @freestore the amount of free store on that path, given in K, M and G
- X- @getenv returns the value of the named env: variable
- X- @howmany indicates the # of shells running
- X- @index returns the index of str2 in str1 (starting at 1)
- X- @info the corresponding line from the 'info' command
- X- @intersect returns all words which are in both lists
- X- @lookfor looks for a file in the current directory and the given paths
- X- @lower lowercases its arguments
- X- @match returns the words in the that match the arp-pattern
- X- @max computes the maximum of all given numbers
- X- @megs expresses a number in K, M and G (-bytes)
- X- @member tells you if the first arg is among the remaining
- X- @min computes the minimum of all given numbers
- X- @nameext returns all after the last dot of filename.
- X- @nameroot returns all before the LAST dot of filename.
- X- @union returns all names that are in either list
- X- @pathname strips the base name from a path
- X- @pickargs picks of its arguments those which don't start with a '-'
- X- @pickopts picks of its arguments those which start witch a '-'
- X- @rpn computes the rpn expression. See rpn command
- X- @sortargs sorts its arguments alphabetically
- X- @split makes each blank separated part of @string a word
- X- @strcmp returns -1, 0 or 1 depending of alphabetical comparison
- X- @strhead see strhead command
- X- @strleft see strleft command
- X- @strmid see strmid command
- X- @strright see strright command
- X- @strtail see strtail command
- X- @subword returns the n-th word of the given list
- X- @subword returns the next m words word of the given list starting from n
- X- @tackon see tackon command
- X- @unique sorts the arguments and makes each of them unique
- X- @upper upper cases the given words
- X- @volume returns the volume name in that path or "" if no disk present
- X- @without returns all names of list 1 that are not in list 2
- X- @word same as @subword
- X- @words returns the number of args
- X
- XBug fixes:
- X
- X- recursive wild card expansion does not crash the Amiga 3000 anymore
- X- recursive wild card expansion does not lose memory anymore
- X- now works on AUX:
- X- trying to start a non-object-file now properly prints 'Command Not Found'
- X- automatic sourcing now also works if you already add .sh to the file name
- X- files longer than 999999 bytes no longer misalign 'dir'
- X- exec does not discard the rest of the command line ('exec echo hi;echo ho')
- X- all memory trashing fixed. Thanks to C= for their great debugging tools!
- X- source doesn't forget last character if batchfile was not CR terminated
- X- run & rback also search AmigaDOS path now
- X- division by zero does not crash rpn anymore
- X- temporary pipe files are now written to t: instead of ram:
- X- shift-tab does not cause a lockup anymore
- X- running the shell via aux: no longer crashes the machine
- X- 'history partial' now numbers the lines correctly
- X- strleft, strright and strmid no longer crash on strings > 256 bytes
- X- source with no arguments now prints correct error message
- X- 'input' now cuts down lines longer than 256 bytes instead of crashing
- X- cursor-up no more deletes lines if there's an invalid entry in the history
- X- if history fails, no empty history entry is generated
- X- 'echo "---"' and even 'echo ---' work, but 'echo "-a"' still doesn't
- X- international character sets can be used
- X- 'copy -u' won't copy a file with identical date stamp but in uppercase
- X- 'copy -u' will no longer access low memory
- X- 'echo "echo mem | shell" | shell' now works, not only every second time
- X- starting from workbench now prevented
- X- editing lines longer than 256 bytes is now correctly prevented
- X- word-right cursor movement works correclty with multiple blanks
- X- 'if'-stack will be adjusted when a batch file is exited
- X- relabel occasionally crashed in Syquest drives. should be okay now
- X
- XNew to 4.02A:
- X
- X- Fixed bug that caused loss of memory on exit.
- X- cp now copies protection bits; use -f switch if you want to avoid this.
- X- Added commands: man (and alias manlist), uniq, head, tail, tee.
- X- This doc has been reformatted to work with man.
- X
- XNew to 4.01A:
- X
- X- This version features mostly bug fixes and corrections:
- X * Window title is restored after quitting.
- X * rxrec now answers to the 'bye' message.
- X * rpn can now be redirected and piped; however, this causes
- X some problem (see rpn for info).
- X * resident list now works with ARP 1.3. To recompile source, you must
- X modify include file "libraries/arpbase.h".
- X Change definition of rpn_Usage in struct ResidentProgramNode from LONG
- X to WORD.
- X * pri no more assumes 20 CLI maximum.
- X * you can now split long lines in source files even into more than 2 lines.
- X- Added much info in this doc about source files (chapter XI)
- X- Added copyright notice (see under restrictions).
- X
- XNew to 4.00A:
- X
- X- This version is called 4.00A because it is not 100% compatible with
- X previous versions. We choose to accept this in order to better support
- X the new ARP.library 1.3.
- X- External commands are searched in a different order than before; Shell
- X path is now searched AFTER current directory, AmigaDOS path and C:.
- X- ARP pattern matching has been implemented (in part for line arg expanding,
- X fully for search -w).
- X- Internal changes for various optimizations.
- X- Search command has been improved in several ways.
- X- New commands: basename, tackon.
- X- New options: if -v, resident -d, fornum -v -s, dir -n.
- X- Fixed bugs with dir (some dirs remained locked), foreach -v, htype
- X (blanks were treated as binary), info (for devices > 32M).
- X- rback command now works ok (run, however, doesn't).
- X- Oh, I forgot: it also has an AREXX port... And you don't even have to get
- X AREXX to use it. See new commands rxsend, rxrec
- X
- XNew to 3.03A:
- X
- X- New filter commands fltlower, fltupper.
- X- Added configuration file feature: now if you have a file named S:.login,
- X it will be sourced for every Shell you start.
- X- New option dir -c.
- X- New editing feature: shift-left(right) arrow move cursor to previous(next)
- X word.
- X- Bugs fixed: alias command wasn't listed in help; typing a number as a
- X command was interpreted like 'alias'.
- X
- XNew to 3.02A:
- X
- X- New commands: fornum, forline, strleft, strright, strmid, strlen, exec.
- X- Improved commands: foreach, pri.
- X- New system variable _clinumber.
- X- You can now split long lines in source files (see source for details).
- X- window -q now lists also position of screens/windows, not only dimension.
- X- Since strings are handled directly from Shell with new commands,
- X rpn is now used only for calculations; string commands are gone.
- X However, now RPN is really usable.
- X- Changed rawgets() to fix some problems with function keys, multi-line
- X editing and window resizing; also, fixed bug with ^E.
- X- cat now warns you if it can't find any file matching your pattern.
- X- Now uses DOS packets to get ptr to CLI window; this fixes a bug that
- X caused problems if Shell was run on unactive windows.
- X- Fixed minor bugs (htype printed some more ASCII bytes, some commands
- X returned random values, history didn't print CR's).
- X- Heavy mods to this file.
- X
- END_OF_FILE
- if test 13639 -ne `wc -c <'changes.doc'`; then
- echo shar: \"'changes.doc'\" unpacked with wrong size!
- fi
- # end of 'changes.doc'
- fi
- if test -f 'rawcon.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rawcon.c'\"
- else
- echo shar: Extracting \"'rawcon.c'\" \(17773 characters\)
- sed "s/^X//" >'rawcon.c' <<'END_OF_FILE'
- X/*
- X * rawcon.c
- X *
- X * Shell 2.07M 17-Jun-87
- X * console handling, command line editing support for Shell
- X * using new console packets from 1.2.
- X * Written by Steve Drew. (c) 14-Oct-86.
- X * 16-Dec-86 Slight mods to rawgets() for Disktrashing.
- X *
- X * Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
- X * Version 5.00L by Urban Mueller 17-Feb-91
- X *
- X */
- X
- X#include "shell.h"
- X
- Xstatic int myget( void );
- Xstatic void myunget(int c);
- Xstatic void setrawcon( long flag, int ievent );
- Xstatic int get_seq( long *param );
- Xstatic int bkspcword( int i, int max, int cnt );
- X
- X
- X#if RAW_CONSOLE
- X
- Xstatic char *tyahdptr, *lasttya;
- Xstatic int tabctr, qcdctr, unget;
- X
- X#define SETRAW setrawcon(-1L,1);
- X#define SETCON setrawcon( 0L,1);
- X
- Xint w_width;
- Xextern char *MenuCommand[MAXMENUS][MAXITEMS];
- X
- X#define CTRL -64
- X#define SHIFT 512
- X#define ESC 1024
- X
- X#define CUP 256
- X#define CDN 257
- X#define CRT 258
- X#define CLT 259
- X#define TAB 9
- X
- Xstatic int Curmap;
- Xstatic USHORT *Keymap[8];
- Xstatic USHORT DefKeymap0[]={
- X CLT, 0, /* CursLt = Move.Left */
- X CRT, 1, /* CursRt = Move.Right */
- X SHIFT+CLT, 2, /* SCursLt= Move.WordL */
- X SHIFT+CRT, 3, /* SCursRt= Move.WordR */
- X ESC+CLT, 4, /* ESC-CLt= Move.SOL */
- X ESC+CRT, 5, /* ESC-CRt= Move.EOL */
- X CTRL+'A', 4, /* ^A = Move.SOL */
- X CTRL+'E', 5, /* ^E = Move.EOL */
- X CTRL+'Z', 4, /* ^Z = Move.SOL */
- X 8, 10, /* BackSp = Del.BackSp */
- X 127, 11, /* Delete = Del.Delete */
- X ESC+ 8, 12, /* ESC-BkS= Del.WordL */
- X ESC+127, 13, /* ESC-Del= Del.WordR */
- X CTRL+'W', 12, /* ^W = Del.WordL */
- X CTRL+'B', 14, /* ^B = Del.SOL */
- X CTRL+'K', 15, /* ^K = Del.EOL */
- X ESC+'x',513, /* ESC-x = Setmap 1 */
- X ESC+'d', 16, /* ESC-d = Del.Line */
- X CTRL+'X', 16, /* ^X = Del.Line */
- X CUP, 20, /* CursUp = Hist.Back */
- X CDN, 21, /* CursDn = Hist.Forw */
- X SHIFT+CUP, 22, /* SCursUp= Hist.Beg */
- X SHIFT+CDN, 23, /* SCursDn= Hist.End */
- X ESC+'!', 24, /* ESC-! = Hist.Compl */
- X ESC+ 13, 25, /* ESC-Ret= Hist.Exec */
- X CTRL+'T', 26, /* ^T = Hist.Tail */
- X TAB, 30, /* Tab = Comp.Norm */
- X SHIFT+TAB, 31, /* STab = Comp.Part */
- X ESC+TAB, 32, /* ESC-TAB= Comp.All */
- X ESC+'c', 33, /* ESC-c = Comp.CD */
- X ESC+'~', 34, /* ESC-~ = Comp.LastCD*/
- X ESC+'i', 40, /* ESC-i = Spec.Insert*/
- X CTRL+'L', 43, /* ^L = Spec.Refr */
- X 10, 44, /* Enter = Spec.Accept*/
- X 13, 44, /* ^Enter = Spec.Accept*/
- X CTRL+'N', 45, /* ^N = Spec.Next */
- X CTRL+'O', 48, /* ^O = Spec.EchoO */
- X CTRL+'\\', 46, /* ^\ = Spec.EOF */
- X 260, 42, /* Help = Misc.Help */
- X 271, 51, /* Menu = Menu */
- X CTRL+'U', 52, /* Undo = Spec.Undo */
- X CTRL+'R', 53, /* Repeat = Spec.Repeat*/
- X 0, 0
- X};
- X
- Xstatic USHORT DefKeymap1[]={
- X 8, 14,
- X 127, 15
- X};
- X
- Xstatic char *Line, *Prompt;
- Xstatic int Pl;
- Xstatic char LastDir[128];
- X
- Xvoid
- Xinitmap(void)
- X{
- X if( !Keymap[0] )
- X Keymap[0]=DefKeymap0, Keymap[1]=DefKeymap1;
- X}
- X
- Xchar *
- Xrawgets( char line[], char prompt[] )
- X{
- X static int inslen, lastrecall=-1;
- X static int lastfn, lastkey;
- X
- X int n, pl, max, i, c, key, fn, cnt;
- X USHORT *p;
- X char *s, *ps, typeahd[256], undo[256];
- X int savn, insert=1, recall, undo_i, undo_max;
- X struct HIST *hist;
- X char **eav=NULL, *ret, fake;
- X int eac, eactr;
- X long param[10], *par;
- X
- X typeahd[0]=0;
- X tyahdptr=lasttya=typeahd;
- X
- X newwidth();
- X
- X if ( o_noraw || !IsInteractive(Input()) ) {
- X if( IsInteractive(Input())) {
- X printf("%s",prompt);
- X fflush(stdout);
- X }
- X return(gets(line));
- X }
- X
- X if (WaitForChar((long)Input(), 100L) || /* don't switch to 1L ...*/
- X CHARSWAIT(stdin)) { /* else causes read err's*/
- X gets(line);
- X return(line);
- X }
- X
- X SETRAW;
- Xbegin:
- X printf("\015%s\033[6n",prompt);
- X fake= savn = pl = n = 0;
- X tyahdptr = typeahd;
- X
- X while( (typeahd[n]=getchar()) != 'R') {
- X if (typeahd[n] == 155) savn = n;
- X if (typeahd[n] == 27 && getchar()=='[')
- X typeahd[n] =155, savn=n;
- X n++;
- X }
- X /* typeahd now contains possible type a head chars
- X followed by <CSI> cursor position report. */
- X
- X typeahd[savn] = '\0';
- X if (typeahd[n-2] != ';') pl = (typeahd[n-2] -'0') * 10;
- X pl += typeahd[n-1] - 49;
- X ps = line + pl;
- X line[max = i = pl] = '\0';
- X
- X Line=line; Prompt=prompt; Pl=pl;
- X
- X if (s = get_var (LEVEL_SET, "_insert")) insert = atoi(s) ? 1 : 0;
- X
- X if( (recall=lastrecall)>=0 ) {
- X lastrecall=-1;
- X goto recallh;
- X }
- X
- X while( (c=myget()) != -1) {
- X int esc=0;
- X key=-1;
- X if( c==27 ) esc=ESC, c=myget();
- X switch(c) {
- X case 155:
- X switch(c=myget()) {
- X case 'A': key=256; break; /* CursUp */
- X case 'B': key=257; break; /* CursDn */
- X case 'C': key=258; break; /* CursRt */
- X case 'D': key=259; break; /* CursLt */
- X case 'T': key=256+SHIFT; break; /* SCursUp */
- X case 'S': key=257+SHIFT; break; /* SCursDn */
- X case ' ':
- X switch( myget() ) {
- X case '@': key=258+SHIFT; break; /* SCursRt */
- X case 'A': key=259+SHIFT; break; /* SCursLt */
- X } break;
- X case 'Z': key=9+SHIFT; break; /* STab */
- X case '?': key=260; myget(); break; /* Help */
- X default :
- X myunget(c);
- X par=param;
- X do {
- X for( *par=0; (c=myget())>='0' && c<='9'; )
- X *par=10* *par + c-'0';
- X par++;
- X } while( c==';' );
- X if( c=='~' ) {
- X key=param[0]+261;
- X if( key>270 ) key+=SHIFT-10;
- X }
- X if( c=='|' ) key=271;
- X } break;
- X default: key=c; break;
- X }
- X key+=esc;
- X
- X for( fn=-1, p=Keymap[Curmap]; *p; p+=2 )
- X if( *p==key )
- X { fn=p[1]; break; }
- X if( fn==-1 && key>=261 && key<=270 || key>=261+SHIFT && key<=270+SHIFT )
- X fn=50;
- X
- X if( fn!=52 && !*lasttya) {
- X memcpy( undo+pl, line+pl, max-pl );
- X undo_i=i; undo_max=max;
- X }
- X
- X switch( fn/512 ) {
- X case 1:
- X fn&=511;
- X if( fn<8 && Keymap[fn] ) Curmap=fn;
- X fn=-2;
- X break;
- X case 2:
- X key=fn&511, fn=-1;
- X break;
- X }
- X
- X if( fn!=-2 )
- X Curmap=0;
- X
- X if( fn!=53 && !*lasttya )
- X lastfn=fn, lastkey=key;
- X
- Xdofn:
- X switch( fn ) {
- X case -2:
- X break;
- X
- X case 0: /* cursor left */
- X if (i > pl)
- X i--, printf("\033[D");
- X break;
- X case 1: /* cursor right */
- X if (i < max)
- X i++, printf("\033[C");
- X break;
- X case 2: /* word left */
- X for (cnt=0; i>pl && line[i-1] == ' '; cnt++,i--);
- X for ( ; i>pl && line[i-1] != ' '; cnt++,i--);
- X if( cnt ) printf("\033[%dD",cnt);
- X break;
- X case 3: /* word right */
- X for( cnt=0; i<max && line[i] != ' '; i++,cnt++) ;
- X for( ; i<max && line[i] == ' '; i++,cnt++) ;
- X if( cnt ) printf("\033[%dC",cnt);
- X break;
- X case 4: /* beg of line */
- X if (i>pl) printf("\033[%dD",i-pl);
- X i = pl;
- X break;
- X case 5: /* end of line */
- X if (i!=max) printf("\033[%dC",max - i);
- X i = max;
- X break;
- X
- X case 10: /* backspace */
- X if (i > pl) {
- X i--;
- X printf("\010");
- X } else break;
- X case 11: /* delete */
- X if (i < max) {
- X int j,t,l = 0;
- X memmove(&line[i],&line[i+1],max-i);
- X --max;
- X printf("\033[P");
- X j = w_width - i % w_width - 1; /* amount to end */
- X t = max/w_width - i/w_width; /* no of lines */
- X for(n = 0; n < t; n++) {
- X l += j; /* # of char moved*/
- X if (j) printf("\033[%dC",j);/* goto eol */
- X printf("%c\033[P",line[w_width*(i/w_width+n+1)-1]);
- X j = w_width-1;
- X }
- X if (t)
- X printf("\033[%dD",l+t); /* get back */
- X }
- X break;
- X case 12: /* bkspc word */
- X cnt= bkspcword(i,max,-1);
- X max-=cnt; i-=cnt;
- X break;
- X case 13:
- X for( cnt=0; i<max && line[i]!=' '; i++,cnt++ ) ;
- X for( ; i<max && line[i]==' '; i++,cnt++ ) ;
- X if ( cnt ) printf("\033[%dC",cnt);
- X cnt=bkspcword(i,max,cnt);
- X i-=cnt; max-=cnt;
- X break;
- X case 14:
- X cnt=bkspcword(i,max,i-pl);
- X i-=cnt; max-=cnt;
- X break;
- X case 16: /* delete line */
- X if (i>pl) printf("\033[%dD",i-pl);
- X i = pl;
- X case 15: /* delete to EOL */
- X printf("\033[J");
- X max = i;
- X line[i] = '\0';
- X break;
- X
- X
- X case 20: /* history up */
- X ++recall;
- X case 21: /* history down */
- X line[pl] = '\0';
- X if (recall >= 0 || fn==20) {
- X if ( fn==21 ) --recall;
- Xrecallh:
- X n=recall;
- X if (recall >= 0) {
- X for(hist = H_head; hist && n--;
- X hist = hist->next);
- X if (hist) strcpy(&line[pl],hist->line);
- X else recall = H_len;
- X }
- X }
- X if (i != pl)
- X printf("\033[%dD",i-pl);
- X printf("\033[J%s",ps);
- X i = max = strlen(ps) + pl;
- X break;
- X case 22: /* beg of hist */
- X recall = H_len-1;
- X case 23: /* end of hist */
- X line[pl] = '\0';
- X if (fn == 23) {
- X recall = 0;
- X if (H_head) strcpy(&line[pl], H_head->line);
- X } else if (H_tail)
- X strcpy(&line[pl], H_tail->line);
- X printf("\015\033[J%s%s", prompt, ps);
- X i = max = strlen(ps) + pl;
- X break;
- X case 24: /* complete hist */
- X line[max]=0;
- X if( s=get_history(&line[pl-1],0 )) {
- X if (i>pl) printf("\033[%dD\033[J",i-pl);
- X line[i=max=pl]=0;
- X strncpy(typeahd,s,256);
- X tyahdptr=typeahd;
- X }
- X break;
- X case 25: /* exec hist */
- X lastrecall= recall;
- X goto done;
- X case 26: /* tail of prev */
- X if( H_head && (s=H_head->line) && (s=index(s,' ')) )
- X tyahdptr=s;
- X break;
- X
- X case 30: /* complete */
- X case 31:
- X case 32:
- X case 33: {
- X static int lastcompl;
- X int j, k, n, e, cnt, len, radlen;
- X char *name, *q, abbrev;
- X
- X abbrev= fn==31;
- Xcomplete:
- X tyahdptr="";
- X if( tabctr!=0 ) {
- X char *dest=typeahd, *lcd;
- X
- X lastcompl=fn;
- X for( cnt=0; i<max && line[i]!=' '; ++i, ++cnt ) ;
- X if(cnt) printf("\033[%dC",cnt);
- X for( e=i, j=i-1, cnt=0; j>=pl && line[j]!=' ' && line[j]!='<' &&
- X line[j]!='>' && line[j]!=';' ; --j ) cnt++;
- X ++j;
- X
- X if( line[j]=='~' && (lcd=get_var(LEVEL_SET,v_lcd))) {
- X strcpy(dest,lcd);
- X dest+=strlen(dest);
- X j++;
- X }
- X memcpy(dest,&line[j],e-j);
- X dest+=e-j;
- X if( fn!=33 )
- X *dest++='*';
- X *dest=0;
- X if( eav ) free_expand( eav ), eav=NULL;
- X breakreset();
- X tabctr=1;
- X if( fn==33 ) {
- X strncpy(LastDir,typeahd,128);
- X if( !quick_cd( name=typeahd+128, LastDir, 0))
- X { putchar(7); break; }
- X } else {
- X eav =expand(typeahd,&eac);
- X if( eac==0 ) { putchar(7); break; }
- X QuickSort(eav, eac);
- X if( fn==30 )
- X name=eav[ eactr=0 ];
- X else
- X name=compile_av(eav,0,eac,' ',1), tabctr=0;
- X }
- X inslen=cnt;
- X } else {
- X abbrev=0, tabctr=1;
- X if( lastcompl==33 ) {
- X quick_cd( name=typeahd+128, LastDir, 1);
- X } else {
- X if( !eac ) break;
- X name=eav[eactr=++eactr % eac];
- X }
- X }
- X len=bkspcword(i,max,inslen);
- X i-=len; max-=len;
- X if( abbrev && eac>1) {
- X strcpy( typeahd, eav[0] );
- X radlen= 9999;
- X for( k=0; k<eac; k++ ) {
- X if ( (n=strlen(eav[k])) < radlen ) radlen=n;
- X for( n=0; n<radlen && eav[0][n]==eav[k][n]; n++ ) ;
- X if ( n<radlen ) radlen=n;
- X }
- X typeahd[radlen]=0;
- X eactr--;
- X } else {
- X if( lastcompl==32 ) {
- X strncpy( typeahd,name,250 );
- X name[250]=0;
- X } else {
- X strcpy(typeahd,(q=index( name, ' ' )) ? "\"" : "" );
- X strcat(typeahd,name);
- X if( q ) strcat(typeahd,"\"");
- X if( lastcompl==33 || isdir(name) )
- X appendslash( typeahd );
- X else
- X strcat( typeahd, " " );
- X }
- X }
- X tyahdptr=typeahd;
- X inslen=strlen(typeahd);
- X }
- X break;
- X case 34:
- X strncpy(typeahd,get_var( LEVEL_SET, v_lcd ),230);
- X appendslash(tyahdptr=typeahd);
- X break;
- X
- X case 40: /* ins/ovr */
- X insert ^= 1;
- X break;
- X case 41: /* quit */
- X strcpy(ps,"quit");
- X goto done;
- X case 42: /* help */
- X strcpy(ps,"help");
- X goto done;
- X case 43: /* refresh */
- X if ((n = i/w_width)) printf("\033[%dF",n);
- X printf("\015\033[J%s%s",prompt,ps);
- X i = max;
- X break;
- X case 44:
- X line[max] = '\0';
- Xdone: printf("\033[%dC\n",max - i);
- X strcpy(line, ps);
- X ret=line;
- X if( fake ) goto begin;
- X goto exit;
- X case 45: /* leave */
- X line[max] = '\0';
- X add_history( ps );
- X fake=1;
- X goto done;
- X case 46: /* EOF */
- X ret=NULL;
- X goto exit;
- X case 47:
- X break;
- X case 48:
- X printf("\017");
- X break;
- X case 49:
- X printf("\07");
- X break;
- X
- X case 50: {
- X char fkeys[8];
- X sprintf(fkeys,"%c%d",param[0]>=10?'F':'f',param[0]%10+1);
- X if (s = get_var(LEVEL_SET, fkeys)) {
- X tyahdptr = strcpy(typeahd,s);
- X a0tospace( tyahdptr );
- X }
- X break;
- X }
- X case 51: {
- X int class=param[0], code=param[2];
- X if( class==10 ) {
- X int num=MENUNUM( code ), item=ITEMNUM( code );
- X tyahdptr="";
- X if( num>=0 && num<MAXMENUS && item>=0 && item<=MAXITEMS )
- X tyahdptr=MenuCommand[num][item];
- X }
- X if( class==11 ) {
- X strcpy(ps,"quit");
- X goto done;
- X }
- X }
- X case 52: {
- X int t;
- X
- X if ((n = i/w_width)) printf("\033[%dF",n);
- X swapmem( undo+pl, line+pl, MAX( max, undo_max)-pl );
- X t=max; max=undo_max; undo_max=t;
- X t=i; i =undo_i; undo_i =t;
- X line[max]=0;
- X printf("\015\033[J%s%s",prompt,ps);
- X if( i<max ) printf("\033[%dD",max-i);
- X }
- X break;
- X case 53:
- X fn=lastfn; key=lastkey;
- X goto dofn;
- X
- X default:
- X key&=255;
- X if (key == 9) key = 32;
- X if (key > 31 && (insert?max:i) < 256) {
- X if (i < max && insert) {
- X int j,t,l = 0;
- X memmove(&line[i+1], &line[i], max - i);
- X printf("\033[@%c",key);
- X t = max/w_width - i/w_width;
- X j = w_width - i % w_width - 1;
- X for(n = 0; n < t; n++) {
- X l += j;
- X if (j) printf("\033[%dC",j);
- X printf("\033[@%c",line[w_width*(i/w_width+n+1)]);
- X j = w_width-1;
- X }
- X if (t) printf("\033[%dD",l + t);
- X ++max;
- X }
- X else {
- X if(i == pl && max == i) printf("\015%s%s",prompt,ps);
- X putchar(key);
- X }
- X line[i++] = key;
- X if (max < i) max = i;
- X line[max] = '\0';
- X }
- X }
- X }
- X ret=NULL;
- Xexit:
- X newwidth();
- X if( eav ) free_expand(eav);
- X SETCON;
- X return ret;
- X}
- X
- Xint
- Xbkspcword( int i, int max, int cnt )
- X{
- X int o=i;
- X
- X if( !cnt ) return 0;
- X
- X if( cnt==-1 ) {
- X cnt=0;
- X while( i>Pl && Line[i-1]==' ' ) i--, cnt++;
- X while( i>Pl && Line[i-1]!=' ' ) i--, cnt++;
- X } else
- X i-=cnt;
- X
- X if( cnt ) printf("\033[%dD",cnt);
- X memmove( Line+i, Line+o, max-o );
- X memset ( Line+max-cnt, ' ', cnt );
- X
- X printf("%s",Line+i);
- X
- X if( max-i ) printf("\033[%dD", max-i );
- X fflush(stdout);
- X Line[max-=cnt]=0;
- X
- X return cnt;
- X}
- X
- Xvoid
- Xsetrawcon( long flag, int ievent ) /* -1L=RAW:, 0L=CON: */
- X{
- X static char menuon, button;
- X long packargs[8];
- X
- X if( !o_nowindow && ievent && flag==0 && menuon)
- X printf("\033[10}"), menuon=0;
- X
- X packargs[0]=flag;
- X SendPacket(994L, packargs, (void *)Myprocess->pr_ConsoleTask);
- X
- X if( !o_nowindow && ievent && flag==-1 ) {
- X if( !menuon )
- X printf("\033[10{"), menuon=1;
- X if( !button )
- X printf("\033[11{"), button=1;
- X }
- X}
- X
- X
- X
- Xstatic int row, height, cnt, noquick=1;
- Xstatic char scrollstr[10];
- X
- Xextern char *Cin_name, *Cout_name;
- Xextern BPTR OldCin;
- X
- Xstatic int FromTee;
- X
- Xvoid
- Xprepscroll( int fromtee )
- X{
- X BPTR truecin=0;
- X long param[8];
- X
- X row=height=0;
- X FromTee=fromtee;
- X
- X if(( noquick=!o_scroll ||o_noraw || o_nofastscr ))
- X return;
- X if(( noquick=Cout_name && !fromtee ))
- X return;
- X if( Cin_name ) {
- X truecin=Myprocess->pr_CIS;
- X
- X if( noquick=!IsInteractive(OldCin) )
- X return;
- X
- X Myprocess->pr_CIS = DEVTAB(stdin) = OldCin;
- X }
- X
- X if( !CHARSWAIT(stdin) ) {
- X SETRAW;
- X fprintf(fromtee?stderr:stdout,"\033[ q");
- X get_seq( param );
- X height=param[2];
- X while( getchar()!='r') ;
- X
- X fprintf(fromtee?stderr:stdout,"\033[6n");
- X get_seq( param );
- X row=param[0];
- X
- X SETCON;
- X
- X cnt= height-row+1;
- X noquick= height<o_minrows;
- X }
- X
- X sprintf(scrollstr,"\033[%cS\033[%cA", o_scroll+'0', o_scroll+'0');
- X
- X if( truecin )
- X Myprocess->pr_CIS = DEVTAB(stdin) = truecin;
- X}
- X
- Xstatic int
- Xget_seq( long *param )
- X{
- X int c;
- X
- X while( (c=getchar())!=155 ) ;
- X do {
- X *param=0;
- X while( (c=getchar())>='0' && c<='9' )
- X *param=10* *param + c-'0';
- X param++;
- X } while( c==';' );
- X
- X return c;
- X}
- X
- X
- Xvoid
- Xquickscroll( void )
- X{
- X if( noquick ) return;
- X
- X if( --cnt<=0 ) {
- X cnt=o_scroll;
- X fprintf( FromTee ? stderr : stdout, "%s",scrollstr);
- X }
- X}
- X
- Xint
- Xdo_keymap( void )
- X{
- X int i, n, len;
- X USHORT *tmp, *put, *get, *map;
- X char *ind;
- X
- X n=myatoi(av[1],0,7);
- X if( atoierr ) return 20;
- X
- X map=Keymap[n]; len=0;
- X if( map )
- X for( len=0; map[2*len]; len++ ) ;
- X
- X put=tmp=malloc((len+ac)*2*sizeof(USHORT));
- X for( i=2; i<ac; i++ ) {
- X if( !(ind=index(av[i],'='))) {
- X ierror( av[i],500);
- X free( tmp );
- X return 20;
- X }
- X *put++=atoi(av[i]);
- X *put++=atoi(ind+1);
- X }
- X
- X for( i=0; i<len; i++ ) {
- X for( get=tmp; get<put; get+=2 )
- X if( *get==map[2*i] )
- X break;
- X if( get==put ) {
- X *put++=map[2*i];
- X *put++=map[2*i+1];
- X }
- X }
- X
- X if( map && map!=DefKeymap0 && map!=DefKeymap1 )
- X free( map );
- X Keymap[n]=tmp;
- X Curmap=0;
- X
- X return 0;
- X}
- X
- Xstatic int
- Xmyget( void )
- X{
- X int c;
- X
- X lasttya=tyahdptr;
- X if( unget )
- X c=unget, unget=0;
- X else if( tyahdptr && *tyahdptr)
- X c=*tyahdptr++;
- X else {
- X#ifndef AZTEC_C
- X fflush(stdout);
- X#endif
- X if( (c=getchar())!=155 )
- X tabctr--, qcdctr--;
- X }
- X
- X return c;
- X}
- X
- Xstatic void
- Xmyunget(int c)
- X{
- X unget=c;
- X}
- X
- Xint
- Xnewwidth( void )
- X{
- X extern struct Window *Win;
- X
- X if( !o_nowindow && Win )
- X w_width=(Win->Width-(Win->BorderLeft+Win->BorderRight))/
- X Win->RPort->TxWidth;
- X else
- X w_width=80;
- X return w_width;
- X}
- X
- X
- X
- X#else
- X
- Xprepscroll(){}
- Xquickscroll(){}
- X
- X#endif
- X
- END_OF_FILE
- if test 17773 -ne `wc -c <'rawcon.c'`; then
- echo shar: \"'rawcon.c'\" unpacked with wrong size!
- fi
- # end of 'rawcon.c'
- fi
- if test -f 'sub.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sub.c'\"
- else
- echo shar: Extracting \"'sub.c'\" \(21051 characters\)
- sed "s/^X//" >'sub.c' <<'END_OF_FILE'
- X
- X/*
- X * SUB.C
- X *
- X * (c)1986 Matthew Dillon 9 October 1986
- X *
- X * Version 2.07M by Steve Drew 10-Sep-87
- X * Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
- X * Version 5.00L by Urban Mueller 17-Feb-91
- X *
- X */
- X
- X#include "shell.h"
- X#include "proto.h"
- X
- Xstatic void del_history( void );
- Xstatic int hasspace( char *s );
- Xstatic int dnext( struct DPTR *dp, char **pname, int *stat);
- Xstatic char *svfile( char *s1, char *s2, FIB *fib);
- Xstatic int exall( BPTR lock, char *path );
- Xstatic void quicksort( char **av, int n );
- X
- X
- X#define HM_STR 0 /* various HISTORY retrieval modes */
- X#define HM_REL 1
- X#define HM_ABS 2
- X
- Xvoid
- Xseterr( void )
- X{
- X char buf[32], *val;
- X int stat=0;
- X
- X sprintf(buf, "%d", Lastresult);
- X set_var(LEVEL_SET, v_lasterr, buf);
- X if( val=get_var(LEVEL_SET, v_stat))
- X stat = atoi(val);
- X if (stat < Lastresult) set_var(LEVEL_SET, v_stat, buf);
- X}
- X
- X#define ISSPACE(c) ((c)==' ' || (c)==9 || (c)==0xA0)
- X
- Xchar *
- Xnext_word( char *str )
- X{
- X while (*str && ! ISSPACE(*str)) ++str;
- X while (*str && ISSPACE(*str)) ++str;
- X return str;
- X}
- X
- Xstatic int
- Xhasspace( char *s )
- X{
- X for ( ; *s; s++)
- X if (ISSPACE(*s)) return 1;
- X return 0;
- X}
- X
- Xchar *
- Xcompile_av(char **av, int start, int end, char delim, int quote)
- X{
- X char *cstr, *p;
- X int len, i;
- X
- X len = 1;
- X for (i = start; i < end; ++i) len += strlen(av[i]) + 3;
- X p = cstr = malloc(len);
- X *cstr = '\0';
- X for (i = start; i < end; ++i) {
- X if (debug) fprintf (stderr, "AV[%2d] :%s:\n", i, av[i]);
- X if (quote && hasspace(av[i]))
- X p += sprintf(p, "\"%s\"", av[i]);
- X else
- X p += sprintf(p, "%s", av[i]);
- X if (i+1 < end) *p++=delim;
- X }
- X *p='\0';
- X return cstr;
- X}
- X
- X/*
- X * FREE(ptr) --frees without actually freeing, so the data is still good
- X * immediately after the free.
- X */
- X
- X
- Xvoid
- XFree( void *ptr )
- X{
- X static char *old_ptr;
- X
- X if (old_ptr) free (old_ptr);
- X old_ptr = ptr;
- X}
- X
- X/*
- X * Add new string to history (H_head, H_tail, H_len,
- X * S_histlen
- X */
- X
- Xvoid
- Xadd_history( char *str )
- X{
- X struct HIST *hist;
- X char *get;
- X
- X for( get=str; *get; get++ )
- X if( (*get&127)<' ')
- X *get=' ';
- X
- X if (H_head != NULL && !strcmp(H_head->line, str))
- X return;
- X while (H_len > S_histlen)
- X del_history();
- X hist = (struct HIST *)malloc (sizeof(struct HIST));
- X if (H_head == NULL) {
- X H_head = H_tail = hist;
- X hist->next = NULL;
- X } else {
- X hist->next = H_head;
- X H_head->prev = hist;
- X H_head = hist;
- X }
- X hist->prev = NULL;
- X hist->line = malloc (strlen(str) + 1);
- X strcpy (hist->line, str);
- X ++H_len;
- X}
- X
- Xstatic void
- Xdel_history()
- X{
- X if (H_tail) {
- X --H_len;
- X ++H_tail_base;
- X free (H_tail->line);
- X if (H_tail->prev) {
- X H_tail = H_tail->prev;
- X free (H_tail->next);
- X H_tail->next = NULL;
- X } else {
- X free (H_tail);
- X H_tail = H_head = NULL;
- X }
- X }
- X}
- X
- Xchar *
- Xget_history( char *ptr, int echo )
- X{
- X struct HIST *hist;
- X int len;
- X int mode = HM_REL;
- X int num = 1;
- X char *str;
- X char *result = NULL;
- X
- X if (ptr[1] >= '0' && ptr[1] <= '9') {
- X mode = HM_ABS;
- X num = atoi(&ptr[1]);
- X goto skip;
- X }
- X switch (ptr[1]) {
- X case '!':
- X break;
- X case '-':
- X num += atoi(&ptr[2]);
- X break;
- X default:
- X mode = HM_STR;
- X str = ptr + 1;
- X break;
- X }
- Xskip:
- X switch (mode) {
- X case HM_STR:
- X len = strlen(str);
- X for (hist = H_head; hist; hist = hist->next) {
- X if (strncmp(hist->line, str, len) == 0 && *hist->line != '!') {
- X result = hist->line;
- X break;
- X }
- X }
- X break;
- X case HM_REL:
- X for (hist = H_head; hist && num--; hist = hist->next);
- X if (hist)
- X result = hist->line;
- X break;
- X case HM_ABS:
- X len = H_tail_base;
- X for (hist = H_tail; hist && len != num; hist = hist->prev, ++len);
- X if (hist)
- X result = hist->line;
- X break;
- X }
- X if( echo )
- X fprintf(stderr, result ? "%s\n" : "History failed\n", result);
- X if( !result ) result="";
- X return result;
- X}
- X
- Xvoid
- Xreplace_head( char *str )
- X{
- X if (str && strlen(str) && H_head) {
- X free (H_head->line);
- X H_head->line = malloc (strlen(str)+1);
- X strcpy (H_head->line, str);
- X }
- X}
- X
- X
- X#if 0
- X#define CDLEN 20
- Xstatic int cd_len=CDLEN, cd_read, cd_write, cd_current;
- Xstatic char *cd_hist[CDLEN];
- X
- Xadd_cdhist( char *str )
- X{
- X if( !str )
- X return;
- X if( cd_hist[cd_write] )
- X free(cd_hist[cd_write]);
- X cd_hist[cd_write++]=str;
- X cd_write%=cd_len;
- X cd_current=cd_write;
- X}
- X
- Xchar *
- Xback_cdhist( void )
- X{
- X if( cd_current!=cd_write ) cd_current= --cd_current % cd_len;
- X return cd_hist[cd_current];
- X}
- X
- Xchar *
- Xforw_cdhist( void )
- X{
- X if( cd_current!=cd_read ) cd_current= ++cd_current % cd_len;
- X return cd_hist[cd_current];
- X}
- X#endif
- X
- Xvoid
- XpError(char *str )
- X{
- X int ierr = (long)IoErr();
- X ierror(str, ierr);
- X}
- X
- Xierror( char *str, int err )
- X{
- X struct PERROR *per = Perror;
- X
- X if (err) {
- X for (; per->errstr; ++per) {
- X if (per->errnum == err) {
- X fprintf (stderr, "%s%s%s\n",
- X per->errstr,
- X (str) ? ": " : "",
- X (str) ? str : "");
- X return err;
- X }
- X }
- X fprintf (stderr, "Unknown DOS error %d %s\n", err, (str) ? str : "");
- X }
- X return err;
- X}
- X
- X/*
- X * Disk directory routines
- X *
- X * dptr = dopen(name, stat)
- X * struct DPTR *dptr;
- X * char *name;
- X * int *stat;
- X *
- X * dnext(dptr, name, stat)
- X * struct DPTR *dptr;
- X * char **name;
- X * int *stat;
- X *
- X * dclose(dptr) -may be called with NULL without harm
- X *
- X * dopen() returns a struct DPTR, or NULL if the given file does not
- X * exist. stat will be set to 1 if the file is a directory. If the
- X * name is "", then the current directory is openned.
- X *
- X * dnext() returns 1 until there are no more entries. The **name and
- X * *stat are set. *stat = 1 if the file is a directory.
- X *
- X * dclose() closes a directory channel.
- X *
- X */
- X
- Xextern long IoError;
- X
- Xstruct DPTR *
- Xdopen( char *name, int *stat)
- X{
- X struct DPTR *dp;
- X
- X *stat = 0;
- X dp = (struct DPTR *)malloc(sizeof(struct DPTR));
- X if (*name == '\0')
- X dp->lock = DupLock(Myprocess->pr_CurrentDir);
- X else
- X dp->lock = Lock (name,ACCESS_READ);
- X if (dp->lock == NULL) {
- X IoError=IoErr();
- X free (dp);
- X return NULL;
- X }
- X dp->fib = (FIB *)AllocMem((long)sizeof(FIB), MEMF_PUBLIC);
- X if (!Examine (dp->lock, dp->fib)) {
- X pError (name);
- X dclose (dp);
- X return NULL;
- X }
- X if (dp->fib->fib_DirEntryType >= 0) *stat = 1;
- X return dp;
- X}
- X
- Xstatic int
- Xdnext( struct DPTR *dp, char **pname, int *stat)
- X{
- X if (dp == NULL) return (0);
- X if (ExNext (dp->lock, dp->fib)) {
- X *stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1;
- X *pname = dp->fib->fib_FileName;
- X return 1;
- X }
- X return 0;
- X}
- X
- Xint
- Xdclose( struct DPTR *dp )
- X{
- X if (dp == NULL)
- X return 1;
- X if (dp->fib)
- X FreeMem (dp->fib,(long)sizeof(*dp->fib));
- X if (dp->lock)
- X UnLock (dp->lock);
- X free (dp);
- X return 1;
- X}
- X
- X
- Xint
- Xisdir( char *file )
- X{
- X struct DPTR *dp;
- X int stat;
- X
- X stat = 0;
- X if (dp = dopen (file, &stat))
- X dclose(dp);
- X return (stat == 1);
- X}
- X
- X
- Xvoid
- Xfree_expand( char **av )
- X{
- X char **get = av;
- X
- X if (av) {
- X while (*get)
- X free (*get++-sizeof(struct file_info));
- X free (av);
- X }
- X}
- X
- X/*
- X * EXPAND(base,pac)
- X * base - char * (example: "df0:*.c")
- X * pac - int * will be set to # of arguments.
- X *
- X * 22-May-87 SJD. Heavily modified to allow recursive wild carding and
- X * simple directory/file lookups. Returns a pointer to
- X * an array of pointers that contains the full file spec
- X * eg. 'df0:c/sear*' would result in : 'df0:C/Search'
- X *
- X * Now no longer necessary to Examine the files a second time
- X * in do_dir since expand will return the full file info
- X * appended to the file name. Set by formatfile().
- X * eg. fullfilename'\0'rwed NNNNNN NNNN DD-MMM-YY HH:MM:SS
- X *
- X * Caller must call free_expand when done with the array.
- X *
- X * base bname = ename =
- X * ------ ------- -------
- X * "*" "" "*"
- X * "!*.info" "" "*.info" (wild_exclude set)
- X * "su*d/*" "" "*" (tail set)
- X * "file.*" "" "file.*"
- X * "df0:c/*" "df0:c" "*"
- X * "" "" "*"
- X * "df0:.../*" "df0:" "*" (recur set)
- X * "df0:sub/.../*" "df0:sub" "*" (recur set)
- X *
- X * ---the above base would be provided by execom.c or do_dir().
- X * ---the below base would only be called from do_dir().
- X *
- X * "file.c" "file.c" "" if (dp == 0) fail else get file.c
- X * "df0:" "df0:" "*"
- X * "file/file" "file/file" "" (dp == 0) so fail
- X * "df0:.../" "df0:" "*" (recur set)
- X *
- X */
- X
- Xint expand_err;
- X
- Xchar **
- Xexpand( char *base, int *pac )
- X{
- X char *ptr;
- X char **eav = (char **)malloc(sizeof(char *) * (2));
- X short eleft, eac;
- X char *name;
- X char *bname, *ename, *tail;
- X int stat, recur, scr, bl;
- X struct DPTR *dp;
- X
- X expand_err = *pac = recur = eleft = eac = 0;
- X
- X base = strcpy(malloc(strlen(base)+1), base);
- X for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr);
- X
- X if (!*ptr) /* no wild cards */
- X --ptr;
- X else
- X for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr);
- X
- X if (ptr < base) {
- X bname = strcpy (malloc(1), "");
- X } else {
- X scr = ptr[1];
- X ptr[1] = '\0';
- X if (!strcmp(ptr-3,".../")) {
- X recur = 1;
- X *(ptr-3) = '\0';
- X }
- X bname = strcpy (malloc(strlen(base)+2), base);
- X ptr[1] = scr;
- X }
- X bl = strlen(bname);
- X ename = ++ptr;
- X for (; *ptr && *ptr != '/'; ++ptr);
- X scr = *ptr;
- X *ptr = '\0';
- X if (scr) ++ptr;
- X tail = ptr;
- X
- X if ((dp = dopen (bname, &stat)) == NULL || (stat == 0 && *ename)) {
- X free (bname);
- X free (base);
- X free (eav);
- X expand_err=1;
- X return (NULL);
- X }
- X
- X if (!stat) { /* eg. 'dir file' */
- X char *p,*s;
- X for(s = p = bname; *p; ++p) if (*p == '/' || *p == ':') s = p;
- X if (s != bname) ++s;
- X *s ='\0';
- X eav[eac++] = svfile(bname,dp->fib->fib_FileName,dp->fib);
- X goto done;
- X }
- X if (!*ename) ename = "*"; /* eg. dir df0: */
- X if (*bname && bname[bl-1] != ':' && bname[bl-1] != '/') { /* dir df0:c */
- X bname[bl] = '/';
- X bname[++bl] = '\0';
- X }
- X while ((dnext (dp, &name, &stat)) && !breakcheck()) {
- X int match = compare_ok(ename,name,0);
- X if (match && !(!recur && *tail)) {
- X if (eleft < 2) {
- X char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
- X memmove (scrav, eav, (eac + 1) << 2);
- X free (eav);
- X eav = scrav;
- X eleft = 10;
- X }
- X eav[eac++] = svfile(bname,name,dp->fib);
- X --eleft;
- X }
- X if ((*tail && match) || recur) {
- X int alt_ac;
- X char *search, **alt_av, **scrav;
- X BPTR lock;
- X
- X if (!stat) /* expect more dirs, but this not a dir */
- X continue;
- X lock = CurrentDir (dp->lock);
- X search = malloc(strlen(ename)+strlen(name)+strlen(tail)+6);
- X strcpy (search, name);
- X strcat (search, "/");
- X if (recur) {
- X strcat(search, ".../");
- X strcat(search, ename);
- X }
- X strcat (search, tail);
- X scrav = alt_av = expand (search, &alt_ac);
- X free(search);
- X CurrentDir (lock);
- X if (scrav) {
- X while (*scrav) {
- X int l;
- X if (eleft < 2) {
- X char **scrav = (char **)malloc(sizeof(char *)*(eac+10));
- X memmove ( scrav, eav, (eac + 1) << 2);
- X free (eav);
- X eav = scrav;
- X eleft = 10;
- X }
- X
- X l = strlen(*scrav);
- X eav[eac] = malloc(bl+l+1+sizeof(struct file_info));
- X memcpy( eav[eac], *scrav-sizeof(struct file_info),
- X sizeof(struct file_info));
- X eav[eac]+=sizeof(struct file_info);
- X strcpy( eav[eac], bname);
- X strcat( eav[eac], *scrav);
- X
- X free (*scrav-sizeof(struct file_info));
- X ++scrav;
- X --eleft, ++eac;
- X }
- X free (alt_av);
- X }
- X }
- X }
- Xdone:
- X dclose (dp);
- X *pac = eac;
- X eav[eac] = NULL;
- X free (bname);
- X free (base);
- X if (eac)
- X return (eav);
- X free (eav);
- X return (NULL);
- X}
- X
- Xchar *
- Xstrupr( char *s )
- X{
- X char *old=s;
- X while (*s) *s=toupper(*s), s++;
- X return old;
- X}
- X
- Xchar *
- Xstrlwr( char *s )
- X{
- X char *old=s;
- X while (*s) *s=tolower(*s), s++;
- X return old;
- X}
- X
- X/*
- X * Compare a wild card name with a normal name
- X */
- X
- Xint
- Xcompare_ok( char *wild, char *name, int casedep)
- X{
- X int queryflag;
- X char buf[260], wildbuf[260], *lowname;
- X
- X if (queryflag=(*wild=='&')) wild++;
- X if (*wild=='!') *wild='~';
- X
- X if (! casedep) {
- X strupr(wild);
- X strcpy(buf,name);
- X strupr(buf);
- X lowname=buf;
- X } else
- X lowname=name;
- X
- X PreParse(wild, wildbuf);
- X if ( ! PatternMatch(wildbuf,lowname)) return 0;
- X
- X if (queryflag) {
- X printf("Select %s%-16s%s [y/n] ? ",o_hilite,name,o_lolite);
- X gets(buf);
- X return (toupper(*buf)=='Y');
- X }
- X return 1;
- X}
- X
- Xstatic char *
- Xsvfile( char *s1, char *s2, FIB *fib)
- X{
- X int len=strlen(s1)+strlen(s2)+1;
- X char *p = malloc (len+sizeof(struct file_info));
- X struct file_info *info;
- X
- X info=(struct file_info *)p;
- X p+=sizeof(struct file_info);
- X strcpy(p, s1);
- X strcat(p, s2);
- X info->flags = fib->fib_Protection;
- X if( fib->fib_DirEntryType<0 ) {
- X info->size = fib->fib_Size;
- X info->blocks= fib->fib_NumBlocks;
- X } else {
- X info->size = -1;
- X info->blocks= 0;
- X }
- X if( fib->fib_Comment[0] )
- X info->flags|= 1<<30;
- X info->date=fib->fib_Date;
- X info->class[0]=1;
- X return p;
- X}
- X
- X
- X
- Xstatic FILE *out;
- Xstatic int NumDirs;
- X
- Xvoid
- Xexpand_all( char *name, FILE *file )
- X{
- X BPTR lock;
- X char path[300];
- X FIB *fib;
- X
- X out=file;
- X printf( " %s\n", name );
- X NumDirs=0;
- X
- X if(fib=AllocMem(sizeof(struct FileInfoBlock),0)) {
- X if( lock=Lock( name, ACCESS_READ )) {
- X strcpy( path, name );
- X exall( lock, path );
- X printf( "\n", NumDirs );
- X }
- X FreeMem(fib,sizeof(struct FileInfoBlock));
- X }
- X}
- X
- Xstatic int
- Xexall( BPTR lock, char *path )
- X{
- X BPTR old, sublock;
- X int len;
- X struct FileInfoBlock *fib;
- X
- X old=CurrentDir( lock );
- X
- X if( !(fib=AllocMem(sizeof(struct FileInfoBlock),0)) )
- X return 1;
- X
- X len=strlen( path );
- X Examine( lock, fib );
- X while( ExNext( lock, fib ) ) {
- X if( fib->fib_DirEntryType>=0 )
- X if( sublock=Lock( fib->fib_FileName, ACCESS_READ )) {
- X if( !len || path[len-1]==':' )
- X sprintf(path+len,"%s", fib->fib_FileName);
- X else
- X sprintf(path+len,"/%s", fib->fib_FileName);
- X fprintf( out, "%s\n", path );
- X fprintf( stdout, " Directories: %d\015", ++NumDirs );
- X fflush ( stdout );
- X if(exall( sublock, path ))
- X break;
- X path[len]=0;
- X }
- X }
- X FreeMem( fib, sizeof(struct FileInfoBlock));
- X CurrentDir( old );
- X return dobreak();
- X}
- X
- X
- X
- X/* Sort routines */
- X
- Xint reverse;
- X
- Xint
- Xcmp( char *s1, char *s2)
- X{
- X int r=Strcmp(s1, s2);
- X return reverse ? -r : r;
- X}
- X
- Xint
- Xsizecmp( char *s1, char *s2)
- X{
- X int r= ((struct file_info *)(s2-sizeof(struct file_info)))->size -
- X ((struct file_info *)(s1-sizeof(struct file_info)))->size;
- X return reverse ? -r : r;
- X}
- X
- Xint
- Xdatecmp( char *s1, char *s2 )
- X{
- X int r;
- X struct DateStamp
- X *d1=&((struct file_info *)(s1-sizeof(struct file_info)))->date,
- X *d2=&((struct file_info *)(s2-sizeof(struct file_info)))->date;
- X if( !(r= d2->ds_Days - d1->ds_Days))
- X if( !(r=d2->ds_Minute - d1->ds_Minute ) )
- X r=d2->ds_Tick - d1->ds_Tick;
- X return reverse ? -r : r;
- X}
- X
- X
- Xstatic void
- Xenterclass( FILEINFO *info )
- X{
- X char *class, *iclass=info->class, *t;
- X
- X if( *iclass==1 ) {
- X if( class=getclass( (char *)(info+1))) {
- X strncpy( iclass, class, 11 );
- X iclass[11]=0;
- X if( t=index(iclass,0xA0))
- X *t=0;
- X } else
- X iclass[0]=0;
- X }
- X}
- X
- Xint
- Xclasscmp( char *s1, char *s2 )
- X{
- X int r;
- X FILEINFO *info1=(FILEINFO *)s1-1, *info2=(FILEINFO *)s2-1;
- X
- X enterclass( info1 );
- X enterclass( info2 );
- X
- X r= Strcmp( info1->class, info2->class );
- X if( !r ) r=Strcmp(s1, s2);
- X return reverse ? -r : r;
- X}
- X
- X
- Xvoid
- XQuickSort( char *av[], int n)
- X{
- X DirQuickSort( av, n, cmp, 0 );
- X}
- X
- Xstatic int (*compare)(char *, char *);
- X
- Xvoid
- XDirQuickSort( char *av[], int n, int (*func)(char *,char *), int rev)
- X{
- X reverse=rev; compare=func;
- X quicksort( av, n-1 );
- X}
- X
- Xstatic void
- Xquicksort( char **av, int n )
- X{
- X char **i, **j, *x, *t;
- X
- X
- X if( n>0 ) {
- X i=av; j=av+n; x=av[ n>>1 ];
- X do {
- X while( (*compare)(*i,x)<0 ) i++;
- X while( (*compare)(x,*j)<0 ) --j;
- X if( i<=j )
- X { t=*i; *i=*j; *j=t; i++; j--; }
- X } while( i<=j );
- X
- X if( j-av < av+n-i ) {
- X quicksort( av, j-av );
- X quicksort( i , av+n-i);
- X } else {
- X quicksort( i , av+n-i);
- X quicksort( av, j-av );
- X }
- X }
- X}
- X
- X
- Xint
- Xfilesize( char *name )
- X{
- X BPTR lock;
- X struct FileInfoBlock *fib;
- X int len=0;
- X
- X if( lock = Lock (name,ACCESS_READ)) {
- X if( fib=(struct FileInfoBlock *)AllocMem(sizeof(*fib),MEMF_PUBLIC)) {
- X if (Examine (lock, fib))
- X len=fib->fib_Size;
- X FreeMem( fib, sizeof(*fib));
- X }
- X UnLock(lock);
- X }
- X return len;
- X}
- X
- X
- X#ifndef MIN
- X#define MIN(x,y) ((x)<(y)?(x):(y))
- X#endif
- X
- Xchar **
- Xand( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
- X{
- X char **av=(char **)malloc(MIN(ac1,ac2)*sizeof(char *) ), *str;
- X int i, j, k=0;
- X
- X for( i=0; i<ac1; i++ )
- X for( j=0, str=base ? BaseName(av1[i]) : av1[i]; j<ac2; j++ )
- X if( !Strcmp(str, base ? BaseName(av2[j]) : av2[j]))
- X av[k++]=av1[i];
- X *ac=k;
- X return av;
- X}
- X
- Xchar **
- Xwithout( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
- X{
- X char **av=(char **)malloc(ac1*sizeof(char *) ), *str;
- X int i, j, k=0;
- X
- X for( i=0; i<ac1; i++ ) {
- X for( j=0, str=base ? BaseName(av1[i]) : av1[i]; j<ac2; j++ )
- X if( !Strcmp(str, base ? BaseName(av2[j]) : av2[j] ) )
- X break;
- X if( j==ac2 )
- X av[k++]=av1[i];
- X }
- X *ac=k;
- X return av;
- X}
- X
- Xchar **
- Xor( char **av1, int ac1, char **av2, int ac2, int *ac, int base )
- X{
- X char **av=(char **)malloc((ac1+ac2)*sizeof(char *) ), *str;
- X int i, j, k=0;
- X
- X for( i=0; i<ac1; i++ )
- X av[k++]=av1[i];
- X
- X for( i=0; i<ac2; i++ ) {
- X for( j=0, str=base ? BaseName(av2[i]) : av2[i]; j<ac1; j++ )
- X if( !Strcmp(str, base ? BaseName(av1[j]) : av1[j] ) )
- X break;
- X if( j==ac1 )
- X av[k++]=av2[i];
- X }
- X
- X *ac=k;
- X return av;
- X}
- X
- Xvoid
- Xclear_archive_bit( char *name )
- X{
- X struct DPTR *dp;
- X int stat;
- X
- X if(dp = dopen(name,&stat) ) {
- X SetProtection( name, dp->fib->fib_Protection&~FIBF_ARCHIVE);
- X dclose( dp );
- X }
- X}
- X
- Xchar *
- Xitoa( int i )
- X{
- X static char buf[20];
- X char *pos=buf+19;
- X int count=4, flag=0;
- X
- X if( i<0 )
- X flag=1, i=-i;
- X
- X do {
- X if( !--count )
- X count=3, *--pos='\'';
- X *--pos= i%10+'0';
- X } while( i/=10 );
- X
- X if( flag )
- X *--pos='-';
- X
- X return pos;
- X}
- X
- Xchar *
- Xitok( int i )
- X{
- X static char buf[16], which;
- X char *exp=" KMG", *ptr= buf+(which=8-which);
- X
- X do
- X i=(i+512)/1024, exp++;
- X while( i>1024 );
- X sprintf( ptr,"%d%c",i,*exp);
- X
- X return ptr;
- X}
- X
- Xchar *
- Xnext_a0( char *str )
- X{
- X while( *str && *str!=0xA0 && *str!='=' && *str!=',') str++;
- X return *str ? str+1 : NULL;
- X}
- X
- Xstatic int
- Xgethex( char *str, int l )
- X{
- X int i, val=0, n, c;
- X
- X if( *str=='.' ) return l==2 ? 256 : 0;
- X
- X for( i=0; i<l || !l; i++ ) {
- X c=*str++;
- X if ( c>='0' && c<='9' ) n=c-'0';
- X else if( c>='a' && c<='f' ) n=c-'a'+10;
- X else if( c>='A' && c<='F' ) n=c-'A'+10;
- X else break;;
- X val=16*val+n;
- X }
- X return (l && i!=l) ? -1 : val;
- X}
- X
- Xstrwrdcmp( char *str, char *wrd )
- X{
- X int len1=strlen(str);
- X char *ind=index(wrd,0xA0);
- X if( ind )
- X return len1!=ind-wrd || Strncmp(str,wrd,len1);
- X else
- X return Strcmp(str,wrd);
- X
- X}
- X
- Xint
- Xwrdlen( char *str )
- X{
- X char *old=str;
- X
- X while( *str && *str!=0xA0 ) str++;
- X return str-old;
- X}
- X
- Xchar *classfile;
- X
- Xchar *
- Xgetclass(char *file)
- X{
- X CLASS *cl;
- X char *class, *str, *arg, *get, *buf;
- X int offs, byte, len, fail;
- X BPTR fh;
- X
- X if( classfile ) {
- X char buf[80];
- X sprintf(buf,"source %s",classfile);
- X execute(buf);
- X classfile=0;
- X }
- X
- X if( isdir(file) ) return "dir";
- X
- X if( !(buf=calloc(1024,1))) return NULL;
- X if( !(fh=Open(file,MODE_OLDFILE))) return NULL;
- X len=Read( fh,buf,1023);
- X Close(fh);
- X
- X for( cl=CRoot; cl; cl=cl->next ) {
- X class=cl->name;
- X if(!(str=next_a0(cl->name))) continue;
- X while( str ) {
- X if(!(arg=next_a0( str ))) goto nextclass;
- X switch( *str ) {
- X case 's':
- X if( (offs=strlen(file)-wrdlen(arg))<0 ) break;
- X if( !strwrdcmp(file+offs,arg)) goto found;
- X break;
- X case 'n':
- X if( !strwrdcmp(BaseName(file),arg) ) goto found;
- X break;
- X case 'd':
- X goto found;
- X case 'o':
- X offs=gethex(arg,0);
- X if( !(arg=index(arg,','))) goto nextclass;
- X if( offs>len-10 ) break;
- X for( get=buf+offs, ++arg; (byte=gethex(arg,2))>=0; arg+=2 )
- X if( *get++!=byte && byte!=256 )
- X goto nexttry;
- X goto found;
- X case 'c':
- X if( !len )
- X goto nexttry;
- X for( get=buf, fail=0; get<buf+len; get++ )
- X if( *get<9 || *get>13 && *get<32 || *get>127 )
- X fail++;
- X if( fail*8>len )
- X goto nexttry;
- X goto found;
- X case 'a':
- X goto nextclass;
- X default:
- X goto nextclass;
- X }
- Xnexttry: str=next_a0(arg);
- X }
- Xnextclass: ;
- X }
- X
- X free(buf);
- X return NULL;
- X
- Xfound:
- X free(buf);
- X return class;
- X}
- X
- Xchar *
- Xgetaction( char *class, char *action )
- X{
- X CLASS *cl;
- X char *cur, *ind;
- X int len;
- X
- X for( len=0; class[len] && class[len]!=0xA0; len++ ) ;
- X for( cl=CRoot; cl; cl=cl->next ) {
- X if( strncmp( cur=cl->name,class,len+1 ))
- X continue;
- X do
- X cur=index( cur,0xA0 );
- X while( cur && *++cur!='a');
- X
- X if( cur && (cur=index( ++cur,0xA0 ))) {
- X do {
- X if( !(ind=index( ++cur,'=' )))
- X return NULL;
- X len=ind-cur;
- X if( len==strlen(action) && !strncmp(action,cur,len))
- X return ++ind;
- X } while( cur=index(cur,0xA0) );
- X }
- X }
- X return NULL;
- X}
- X
- Xint
- Xdoaction( char *file, char *action, char *args )
- X{
- X char *class, *com, *c, *copy;
- X
- X if( !(class=getclass(file)))
- X return 10;
- X if( !(com=getaction(class,action)))
- X return 11;
- X if( c=index(com,0xA0) )
- X *c=0;
- X copy=malloc( strlen(com)+strlen(file)+strlen(args)+5 );
- X sprintf(copy,"%s %s %s",com,file,args);
- X execute(copy);
- X free(copy);
- X if( c )
- X *c=0xA0;
- X return 0;
- X}
- END_OF_FILE
- if test 21051 -ne `wc -c <'sub.c'`; then
- echo shar: \"'sub.c'\" unpacked with wrong size!
- fi
- # end of 'sub.c'
- fi
- echo shar: End of archive 2 \(of 6\).
- cp /dev/null ark2isdone
- MISSING=""
- for I in 1 2 3 4 5 6 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 6 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
- Mail comments to the moderator at <amiga-request@uunet.uu.net>.
- Post requests for sources, and general discussion to comp.sys.amiga.misc.
-